package com.love.marriage.TecentIm.service.impl;

import com.alibaba.fastjson.JSONObject;
import com.love.marriage.TecentIm.service.WuKongImService;
import com.love.marriage.TecentIm.vo.LocalImChatListVo;
import com.love.marriage.TecentIm.vo.WuKongImUserVo;
import com.love.marriage.common.constants.RedisConstants;
import com.love.marriage.utils.RedisUtils;
import com.love.marriage.utils.StringUtils;
import lombok.extern.slf4j.Slf4j;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.beans.factory.annotation.Value;
import org.springframework.http.HttpEntity;
import org.springframework.http.HttpHeaders;
import org.springframework.http.MediaType;
import org.springframework.http.ResponseEntity;
import org.springframework.stereotype.Service;
import org.springframework.web.client.RestTemplate;

import java.text.SimpleDateFormat;
import java.util.*;
import java.util.concurrent.TimeUnit;

/**
 * WuKongIM 服务实现类
 * 实现单人之间的即时通讯功能
 * 文档：https://docs.githubim.com/zh/api/introduction
 * WuKongIM 集成实现
 */
@Service
@Slf4j
public class WuKongImServiceImpl implements WuKongImService {

    private final RestTemplate restTemplate;

    @Autowired
    private RedisUtils redisUtils;

    // WuKongIM API 基地址
    @Value("${wukong.im.api.url:http://localhost:5001}")
    private String apiBaseUrl;

    // 缓存前缀
    private static final String WUKONG_IM_USER_PREFIX = "wukong_im_user";

    public WuKongImServiceImpl(RestTemplate restTemplate) {
        this.restTemplate = restTemplate;
    }

    /**
     * 发送单人消息
     * 调用 WuKongIM API 的发送消息接口
     * API: POST /message/send
     * 单人聊天使用频道类型 1（个人频道）
     */
    @Override
    public Long sendMessage(String fromUid, String toUid, String messageContent) {
        try {
            String url = apiBaseUrl + "/message/send";
            // 对消息内容进行 Base64 编码
            String encodedPayload = Base64.getEncoder().encodeToString(messageContent.getBytes());
            JSONObject requestBody = new JSONObject();
            requestBody.put("channel_id", toUid);
            requestBody.put("channel_type", 1);  // 1 = 个人频道（一对一私聊）
            requestBody.put("from_uid", fromUid);
            requestBody.put("payload", encodedPayload);

            HttpHeaders headers = getHeaders();
            HttpEntity<String> entity = new HttpEntity<>(requestBody.toJSONString(), headers);

            ResponseEntity<JSONObject> response = restTemplate.postForEntity(url, entity, JSONObject.class);

            if (response.getStatusCode().is2xxSuccessful() && response.getBody() != null) {
                Long messageId = (Long) ((Map<String, Object>) (response.getBody().get("data"))).get("message_id");
                log.info("发送消息成功 - from: {}, to: {}, messageId: {}", fromUid, toUid, messageId);
                return messageId;
            }
        } catch (Exception e) {
            log.error("发送消息失败 - from: {}, to: {}, 错误: {}", fromUid, toUid, e.getMessage(), e);
        }
        return null;
    }

    /**
     * 获取IM聊天列表
     * 调用 WuKongIM API 的会话同步接口
     * API: POST /conversation/sync
     * 文档: https://docs.githubim.com/zh/api/conversation/sync
     * 获取会话列表，并转换为 LocalImChatListVo 列表
     *
     * @param uid          用户ID
     * @param syncSequence 同步序列号
     * @param limit        限制数量
     * @return 聊天列表
     */
    @Override
    public List<LocalImChatListVo> getImChatList(String uid, Long syncSequence, Integer limit) {
        List<LocalImChatListVo> chatList = new ArrayList<>();

        try {
            String url = apiBaseUrl + "/conversation/sync";

            // 构建请求体（会话同步格式）
            JSONObject requestBody = new JSONObject();

            // 必传参数
            requestBody.put("uid", uid);
            if (syncSequence != null) {
                requestBody.put("sync_sequence", syncSequence);
            }
            requestBody.put("msg_count", 2);
            requestBody.put("limit", limit != null ? limit : 30);

            HttpHeaders headers = getHeaders();
            HttpEntity<String> entity = new HttpEntity<>(requestBody.toJSONString(), headers);

            ResponseEntity<Object> response = restTemplate.postForEntity(url, entity, Object.class);
            log.info("消息列表响应:{}", JSONObject.toJSONString(response));
            if (response.getStatusCode().is2xxSuccessful() && response.getBody() != null) {
                // 将响应转换为 LocalImChatListVo 列表
                chatList = convertToLocalImChatList(response.getBody(), uid);
                log.info("获取IM聊天列表成功 - uid: {}, 返回数量: {}", uid, chatList.size());
                return chatList;
            }
            log.error("获取IM聊天列表失败 - uid: {}, 响应状态码: {}", uid, response.getStatusCode());
        } catch (Exception e) {
            log.error("获取IM聊天列表失败 - uid: {}, 错误: {}", uid, e.getMessage(), e);
        }
        return chatList;
    }

    /**
     * 将 WuKongIM 消息响应转换为 LocalImChatListVo 列表
     * 数据格式转换方法，处理会话同步响应
     */
    private List<LocalImChatListVo> convertToLocalImChatList(Object responseList, String currentUserId) {
        List<LocalImChatListVo> chatList = new ArrayList<>();
        if (responseList == null) {
            log.warn("WuKongIM 响应数据为空");
            return chatList;
        }
        try {
            // 类型转换处理
            List<Map<String, Object>> conversations = (List<Map<String, Object>>) responseList;
            if (conversations.isEmpty()) {
                log.warn("没有会话数据 - currentUserId: {}", currentUserId);
                return chatList;
            }
            // 遍历每个会话，提取最后一条消息转换为 LocalImChatListVo
            for (Map<String, Object> conversation : conversations) {
                // 获取会话的 recents 数组（最近消息列表）
                @SuppressWarnings("unchecked")
                List<Map<String, Object>> recents = conversation.get("recents") != null ?
                        (List<Map<String, Object>>) conversation.get("recents") : new ArrayList<>();
                if (recents == null || recents.isEmpty()) {
                    continue;
                }
                // 获取记录中 timestamp 最大的那条记录（最新的消息）
                Map<String, Object> lastMsg = recents.stream()
                        .max((msg1, msg2) -> {
                            Integer timestamp1 = (Integer) msg1.get("timestamp");
                            Integer timestamp2 = (Integer) msg2.get("timestamp");
                            if (timestamp1 == null || timestamp2 == null) {
                                return 0;
                            }
                            return Integer.compare(timestamp1, timestamp2);
                        })
                        .orElse(recents.get(recents.size() - 1));
                LocalImChatListVo chatVo = new LocalImChatListVo();
                // 设置当前用户ID
                chatVo.setUid(Long.valueOf(currentUserId));
                // 获取对话对象的用户ID（从频道ID或channel_id）
                String toUid = (String) conversation.get("channel_id");
                if (StringUtils.isNotBlank(toUid)) {
                    chatVo.setToUid(Long.valueOf(toUid));
                }
                // 解析消息payload（Base64编码）
                String payloadStr = (String) lastMsg.get("payload");
                if (StringUtils.isNotBlank(payloadStr)) {
                    try {
                        byte[] decodedBytes = Base64.getDecoder().decode(payloadStr);
                        String messageContent = new String(decodedBytes);
                        chatVo.setMessageInfo(messageContent);
                    } catch (IllegalArgumentException e) {
                        log.warn("payload Base64解码失败: {}", payloadStr);
                        chatVo.setMessageInfo(payloadStr);
                    }
                }
                // 时间戳转换为日期字符串
                // timestamp 是 10 位秒级时间戳（不是毫秒），直接使用不需要乘以 1000
                Integer timestamp = (Integer) lastMsg.get("timestamp");
                if (timestamp != null) {
                    SimpleDateFormat sdf = new SimpleDateFormat("yyyy-MM-dd HH:mm:ss");
                    String dateStr = sdf.format(new Date(timestamp * 1000L));
                    chatVo.setCreatedAt(dateStr);
                    chatVo.setUpdatedAt(dateStr);
                }
                chatVo.setUnreadCount((Integer) conversation.get("unread"));
                // 其他字段映射
                chatVo.setMode(1);  // 默认模式
                chatList.add(chatVo);
            }
            // 按照更新时间倒序排列（最新的在前）
            chatList.sort((a, b) -> {
                try {
                    SimpleDateFormat sdf = new SimpleDateFormat("yyyy-MM-dd HH:mm:ss");
                    java.util.Date dateA = sdf.parse(a.getUpdatedAt());
                    java.util.Date dateB = sdf.parse(b.getUpdatedAt());
                    return dateB.compareTo(dateA);  // 倒序排列
                } catch (Exception e) {
                    log.error("日期比较失败: {}", e.getMessage());
                    return 0;
                }
            });
            log.info("成功转换消息列表 - 会话数: {}, 转换数量: {}", conversations.size(), chatList.size());
        } catch (Exception e) {
            log.error("转换消息数据失败 - 错误: {}", e.getMessage(), e);
        }
        return chatList;
    }

    /**
     * 获取IM聊天记录
     * 调用 WuKongIM API: POST /channel/messagesync
     * 文档: https://docs.githubim.com/zh/api/message/message-sync
     * 获取用户的聊天历史记录（消息），返回Map列表
     *
     * @param loginUid        当前登录用户ID
     * @param channelId       频道ID
     * @param channelType     频道类型
     * @param startMessageSeq 开始消息序号
     * @param endMessageSeq   结束消息序号
     * @param limit           限制数量
     * @return 聊天记录列表
     */
    @Override
    public List<Map<String, Object>> getImChatHistory(String loginUid, String channelId, Integer channelType, Long startMessageSeq, Long endMessageSeq, Integer limit) {
        try {
            String url = apiBaseUrl + "/channel/messagesync";

            // 构建请求体（消息同步格式）
            JSONObject requestBody = new JSONObject();
            requestBody.put("login_uid", loginUid);
            requestBody.put("channel_id", channelId);
            requestBody.put("channel_type", channelType != null ? channelType : 1);  // 默认为个人频道
            if (startMessageSeq != null) {
                requestBody.put("start_message_seq", startMessageSeq);
            }
            if (endMessageSeq != null) {
                requestBody.put("end_message_seq", endMessageSeq);
            }
            requestBody.put("limit", limit != null ? limit : 30);
            requestBody.put("pull_mode", 1);
            HttpHeaders headers = getHeaders();
            HttpEntity<String> entity = new HttpEntity<>(requestBody.toJSONString(), headers);
            ResponseEntity<Object> response = restTemplate.postForEntity(url, entity, Object.class);
            log.info("响应结果：{}", JSONObject.toJSONString(response));
            if (response.getStatusCode().is2xxSuccessful() && response.getBody() != null) {
                // 解析响应体中的消息列表
                @SuppressWarnings("unchecked")
                Map<String, Object> responseBody = (Map<String, Object>) response.getBody();

                @SuppressWarnings("unchecked")
                List<Map<String, Object>> messages = (List<Map<String, Object>>) responseBody.get("messages");

                if (messages == null || messages.isEmpty()) {
                    log.warn("聊天记录为空 - loginUid: {}, channelId: {}", loginUid, channelId);
                    return new ArrayList<>();
                }

                // 遍历消息列表，解析 timestamp 和 payload
                List<Map<String, Object>> chatHistory = new ArrayList<>();
                messages.forEach(msg -> {
                    try {
                        Map<String, Object> messageMap = new LinkedHashMap<>();

                        // 复制原始字段
                        messageMap.putAll(msg);

                        // 解析 timestamp（10位秒级时间戳）
                        Integer timestamp = (Integer) msg.get("timestamp");
                        if (timestamp != null) {
                            SimpleDateFormat sdf = new SimpleDateFormat("yyyy-MM-dd HH:mm:ss");
                            String timeStr = sdf.format(new Date(timestamp * 1000L));
                            messageMap.put("timestamp_str", timeStr);
                        }

                        // 解析 payload（Base64编码）
                        String payloadStr = (String) msg.get("payload");
                        if (StringUtils.isNotBlank(payloadStr)) {
                            try {
                                byte[] decodedBytes = Base64.getDecoder().decode(payloadStr);
                                String messageContent = new String(decodedBytes);
                                messageMap.put("message_content", messageContent);
                            } catch (IllegalArgumentException e) {
                                log.warn("payload Base64解码失败: {}", payloadStr);
                                messageMap.put("message_content", payloadStr);
                            }
                        }

                        chatHistory.add(messageMap);
                    } catch (Exception e) {
                        log.error("解析消息失败: {}", e.getMessage(), e);
                    }
                });

                // 反转消息列表顺序（从最新到最旧变成从最旧到最新）
//                java.util.Collections.reverse(chatHistory);

                log.info("获取IM聊天记录成功 - loginUid: {}, channelId: {}, 返回记录数: {}", loginUid, channelId, chatHistory.size());
                return chatHistory;
            }
            log.error("获取IM聊天记录失败 - loginUid: {}, channelId: {}, 响应状态码: {}", loginUid, channelId, response.getStatusCode());
        } catch (Exception e) {
            log.error("获取IM聊天记录失败 - loginUid: {}, channelId: {}, 错误: {}", loginUid, channelId, e.getMessage(), e);
        }
        return new ArrayList<>();
    }

    /**
     * 设置会话未读数
     * 调用 WuKongIM API: POST /conversation/set-unread
     * 文档: https://docs.githubim.com/zh/api/conversation/set-unread
     *
     * @param uid         用户ID
     * @param channelId   频道ID
     * @param channelType 频道类型
     * @param unreadCount 未读数量
     * @return 设置结果
     */
    @Override
    public Object setConversationUnread(String uid, String channelId, Integer channelType, Integer unreadCount) {
        try {
            String url = apiBaseUrl + "/conversations/setUnread";

            // 构建请求体
            JSONObject requestBody = new JSONObject();
            requestBody.put("uid", uid);
            requestBody.put("channel_id", channelId);
            requestBody.put("channel_type", channelType);
            requestBody.put("unread", unreadCount);

            HttpHeaders headers = getHeaders();
            HttpEntity<String> entity = new HttpEntity<>(requestBody.toJSONString(), headers);

            ResponseEntity<Object> response = restTemplate.postForEntity(url, entity, Object.class);

            if (response.getStatusCode().is2xxSuccessful() && response.getBody() != null) {
                log.info("设置会话未读数成功 - uid: {}, channelId: {}", uid, channelId);
                return response.getBody();
            }
            log.error("设置会话未读数失败 - uid: {}, channelId: {}, 响应状态码: {}", uid, channelId, response.getStatusCode());
        } catch (Exception e) {
            log.error("设置会话未读数失败 - uid: {}, channelId: {}, 错误: {}", uid, channelId, e.getMessage(), e);
        }
        return null;
    }

    /**
     * 获取 HTTP 请求头
     * 根据 WuKongIM API 文档，Content-Type 必须为 application/json
     */
    private HttpHeaders getHeaders() {
        HttpHeaders headers = new HttpHeaders();
        headers.setContentType(MediaType.APPLICATION_JSON);
        return headers;
    }

    /**
     * 用户登录或注册
     * 先从Redis缓存中获取token，没有则创建用户并生成token后存储
     * 优先使用缓存的token，缓存命中直接返回，未命中则调用API创建并缓存
     */
    @Override
    public Object loginOrRegister(String userId) {
        try {
            // 第一步：优先从缓存中获取token
            String cacheKey = WUKONG_IM_USER_PREFIX + RedisConstants.SEGMENTATION + userId;
            String cachedToken = redisUtils.get(cacheKey);

            if (StringUtils.isNotBlank(cachedToken)) {
                log.info("用户登录缓存命中 - userId: {}, token: {}", userId, cachedToken);
                return cachedToken;
            }
            // 第二步：缓存未命中，创建用户
            log.info("用户登录缓存未命中，创建用户 - userId: {}", userId);
            String url = apiBaseUrl + "/user/token";
            String token = UUID.randomUUID().toString();
            // 构建更新 token 请求
            JSONObject requestBody = new JSONObject();
            requestBody.put("uid", userId);
            requestBody.put("token", token);
            requestBody.put("device_flag", 0);
            requestBody.put("device_level", 0);
            HttpHeaders headers = getHeaders();
            HttpEntity<String> entity = new HttpEntity<>(requestBody.toJSONString(), headers);
            ResponseEntity<JSONObject> response = restTemplate.postForEntity(url, entity, JSONObject.class);
            if (response.getStatusCode().is2xxSuccessful()) {
                redisUtils.setEx(cacheKey, token, 86400, TimeUnit.SECONDS);
                log.info("用户登录或注册成功 - userId: {}, token: {}", userId, token);
                return token;
            }
        } catch (Exception e) {
            log.error("用户登录或注册失败 - userId: {}, 错误: {}", userId, e.getMessage(), e);
        }
        return null;
    }

    /**
     * 获取用户登录状态和信息
     * 仅从缓存中获取，不进行网络请求
     * 获取缓存的用户信息
     */
    @Override
    public Object getUserLoginStatus(String userId) {
        try {
            String cacheKey = WUKONG_IM_USER_PREFIX + RedisConstants.SEGMENTATION + userId;
            String cachedUserInfo = redisUtils.get(cacheKey);

            if (StringUtils.isNotBlank(cachedUserInfo)) {
                log.info("获取用户登录状态成功 - userId: {}", userId);
                return JSONObject.parse(cachedUserInfo);
            } else {
                log.warn("用户未登录或缓存已过期 - userId: {}", userId);
                WuKongImUserVo userVo = new WuKongImUserVo();
                userVo.setUserId(userId);
                userVo.setLoginStatus(false);
                userVo.setErrorMessage("用户未登录或缓存已过期");
                return userVo;
            }
        } catch (Exception e) {
            log.error("获取用户登录状态失败 - userId: {}, 错误: {}", userId, e.getMessage(), e);
        }
        return null;
    }

    /**
     * 获取集群会话消息列表
     * 调用 WuKongIM 集群会话接口获取用户的会话列表
     *
     * @param uid 用户ID
     * @return 聊天列表
     */
    @Override
    public List<LocalImChatListVo> getImChatList1(String uid, Long syncSequence, Integer limit) {
        List<LocalImChatListVo> chatList = new ArrayList<>();

        try {
            String url = apiBaseUrl + "/cluster/conversations?uid=" + uid;

            // 使用 GET 请求获取会话列表
            ResponseEntity<Object> response = restTemplate.getForEntity(url, Object.class);
            log.info("集群会话消息响应:{}", JSONObject.toJSONString(response));

            if (response.getStatusCode().is2xxSuccessful() && response.getBody() != null) {
                // 将响应转换为 LocalImChatListVo 列表
                chatList = convertToLocalImChatList1(response.getBody(), uid);
                log.info("获取集群会话消息成功 - uid: {}, 返回数量: {}", uid, chatList.size());
            } else {
                log.warn("获取集群会话消息失败 - uid: {}, 响应状态码: {}", uid, response.getStatusCode());
            }
        } catch (Exception e) {
            log.error("获取集群会话消息失败 - uid: {}, 错误: {}", uid, e.getMessage(), e);
        }

        return chatList;
    }

    /**
     * 将 WuKongIM 消息响应转换为 LocalImChatListVo 列表
     * 数据格式转换方法，处理会话同步响应
     */
    private List<LocalImChatListVo> convertToLocalImChatList1(Object responseList, String currentUserId) {
        List<LocalImChatListVo> chatList = new ArrayList<>();
        Object data = ((Map<String, Object>) responseList).get("data");
        if (data == null) {
            log.warn("WuKongIM 响应数据为空");
            return chatList;
        }
        try {
            // 类型转换处理
            List<Map<String, Object>> conversations = (List<Map<String, Object>>) data;
            if (conversations.isEmpty()) {
                log.warn("没有会话数据 - currentUserId: {}", currentUserId);
                return chatList;
            }
            // 遍历每个会话，提取最后一条消息转换为 LocalImChatListVo
            for (Map<String, Object> conversation : conversations) {
                // 获取会话的 recents 数组（最近消息列表）
                // 获取记录中 timestamp 最大的那条记录（最新的消息）
                LocalImChatListVo chatVo = new LocalImChatListVo();
                // 设置当前用户ID
                chatVo.setUid(Long.valueOf(currentUserId));
                // 获取对话对象的用户ID（从频道ID或channel_id）
                String toUid = ((String) conversation.get("channel_id")).replace("" + currentUserId, "").replace("@", "");
                if (StringUtils.isNotBlank(toUid)) {
                    chatVo.setToUid(Long.valueOf(toUid));
                }
                Integer createdTime = (Integer) conversation.get("created_at");
                Integer updatedTime = (Integer) conversation.get("updated_at");
                chatVo.setCreatedTime(createdTime);
                chatVo.setUpdatedTime(updatedTime);
                // Convert createdTime to time string format
                if (createdTime != null) {
                    SimpleDateFormat sdf = new SimpleDateFormat("yyyy-MM-dd HH:mm:ss");
                    String createdTimeStr = sdf.format(new Date(createdTime * 1000L));
                    chatVo.setCreatedAt(createdTimeStr);
                } else {
                    chatVo.setCreatedAt((String) conversation.get("created_at_format"));
                }

                // Convert updatedTime to time string format
                if (updatedTime != null) {
                    SimpleDateFormat sdf = new SimpleDateFormat("yyyy-MM-dd HH:mm:ss");
                    String updatedTimeStr = sdf.format(new Date(updatedTime * 1000L));
                    chatVo.setUpdatedAt(updatedTimeStr);
                } else {
                    chatVo.setUpdatedAt((String) conversation.get("updated_at_format"));
                }
                chatVo.setCreatedTime(createdTime);
                chatVo.setUpdatedTime(updatedTime);
                // 其他字段映射
                chatVo.setMode(1);  // 默认模式
                List<Map<String, Object>> imChatHistory = getImChatHistory(currentUserId, toUid, 1, null, null, 5);
                if (!imChatHistory.isEmpty()) {
                    String message = (String) imChatHistory.get(0).get("message_content");
                    chatVo.setMessageInfo(message);
                }
                chatList.add(chatVo);
            }
            // 按照更新时间倒序排列（最新的在前）
            chatList.sort((a, b) -> {
                try {
                    Integer updatedTimeA = a.getUpdatedTime();
                    Integer updatedTimeB = b.getUpdatedTime();
                    return updatedTimeB.compareTo(updatedTimeA);  // 倒序排列
                } catch (Exception e) {
                    log.error("日期比较失败: {}", e.getMessage());
                    return 0;
                }
            });
            log.info("成功转换消息列表 - 会话数: {}, 转换数量: {}", conversations.size(), chatList.size());
        } catch (Exception e) {
            log.error("转换消息数据失败 - 错误: {}", e.getMessage(), e);
        }
        return chatList;
    }
}

